package com.kk.service.impl;

import com.kk.base.Constant;
import com.kk.model.Menu;
import com.kk.model.Role;
import com.kk.model.RoleMenuRel;
import com.kk.model.User;
import com.kk.model.enumbean.LevelEnum;
import com.kk.repository.MenuRepository;
import com.kk.repository.RoleMenuRelRepository;
import com.kk.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author: kevin
 * @data: 2018-08-22 10:08
 * @desc:
 */
@Service
class MenuServiceImpl implements MenuService {

    @Autowired
    private RoleMenuRelRepository roleMenuRelRepository;
    @Autowired
    private MenuRepository menuRepository;

    @Override
    public List<Menu> getMenuTreeList(List<Menu> topMenuList, List<Menu> allMenuList) {
        List<Menu> result = new ArrayList<>();
        for (Menu menu : topMenuList) {
            Set<Menu> childMenus = getChildMenuList(menu, allMenuList);
            menu.setChilds(childMenus);
            if (menu.getMenuType() == Constant.TYPE_MENU) {
                result.add(menu);
            }
        }
        return result;
    }

    @Override
    public Set<Menu> getChildMenuList(Menu parentMenu, List<Menu> allMenuList) {
        Set<Menu> result = new HashSet<>();
        for (Menu menu : allMenuList) {
            if (parentMenu.equals(menu.getParent())) {
                if (menu.getMenuType() == Constant.TYPE_MENU) {
                    result.add(menu);
                }
            }
        }
        return result;
    }

    @Override
    public List<Menu> getTopMenuList(User user) {
        Set<Set<RoleMenuRel>> roleMenuRelSet = new HashSet<>();
        for (Role role : user.getRoles()) {
            roleMenuRelSet.add(roleMenuRelRepository.findByRoleId(role.getId()));
        }
        Set<Menu> menuSet = new HashSet<>();
        for (Set<RoleMenuRel> roleMenuRels : roleMenuRelSet) {
            for (RoleMenuRel roleMenuRel : roleMenuRels) {
                if (LevelEnum.ONE.name().equals(roleMenuRel.getMenu().getLevel().name()) &&roleMenuRel.getMenu().getMenuType() == Constant.TYPE_MENU) {
                    if (isExistById(roleMenuRel.getMenu().getId())) {
                        menuSet.add(roleMenuRel.getMenu());
                    }
                }
            }
        }
        List<Menu> menus = new ArrayList<>(menuSet);
        Collections.sort(menus, (o1, o2) -> o1.getSort() < o2.getSort() ? -1 : 1);
        return menus;
    }

    /**
     * 通过Set无序不可重复的特性将一个用户下面N个角色的所有菜单都汇总到一个Set集合中，
     * 但需要重写实体类的hashCode和equals方法，BaseEntity中重写了这两个方法，
     * 因为除String等封装类型外(它们本身重写了这两个方法)，普通类的hashCode方法是继承Object的，然而Object比较的是
     * 对象的引用地址，new 出来的两个对象它们的引用地址显然不同，故如不重写实体类的hashCode和equals方法，
     * Set集合就起不到去重的作用
     *
     * @param user 用户
     * @return
     */
    @Override
    public List<Menu> getAllMenuList(User user) {
        Set<Set<RoleMenuRel>> roleMenuRelSet = new HashSet<>();
        for (Role role : user.getRoles()) {
            roleMenuRelSet.add(roleMenuRelRepository.findByRoleId(role.getId()));
        }
        Set<Menu> menuSet = new HashSet<>();
        for (Set<RoleMenuRel> roleMenuRels : roleMenuRelSet) {
            for (RoleMenuRel roleMenuRel : roleMenuRels) {
                if (roleMenuRel.getMenu().getMenuType() == Constant.TYPE_MENU) {
                    if (isExistById(roleMenuRel.getMenu().getId())) {
                        menuSet.add(roleMenuRel.getMenu());
                    }
                }
            }
        }
        List<Menu> menus = new ArrayList<>(menuSet);
        Collections.sort(menus, (o1, o2) -> o1.getSort() < o2.getSort() ? -1 : 1);
        return menus;
    }

    @Override
    public List<Menu> getButtonList(User user) {
        return null;
    }

    @Override
    public boolean isExistById(String id) {
        Optional<Menu> menu = menuRepository.findById(id);
        if(menu!=null && menu.isPresent()){
            return true;
        }
        return false;
    }

}
